/**
 * 
 */
package com.taobao.api;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.taobao.api.util.DateUtil;
import com.taobao.api.util.EncryptUtil;

/**
 * Rest风格客户端的抽象类
 * 
 * @version 2008-11-18
 * @author <a href="mailto:zixue@taobao.com">zixue</a>
 * 
 */
public abstract class AbstractTaobaoRestClient implements RestClient {
	/**
	 * 淘宝API入口
	 */
	public static final String API_SERVICE_URL = "http://gw.api.taobao.com/router/rest";

	/**
	 * 淘宝API沙箱环境入口
	 */
	public static final String API_SANDBOX_SERVICE_URL = "http://gw.sandbox.taobao.com/router/rest";

	public static final String FORMAT = "format";
	public static final String JSON_FORMAT = "json";
	public static final String V = "v";

	// 系统级参数
	public static final String APIKEY = "api_key";
	public static final String METHOD = "method";
	public static final String SESSION = "session";
	public static final String SIGN = "sign";
	public static final String TIMESTAMP = "timestamp";
	// 默认版本号
	public static final String DEFAULT_SERVICE_VERSION = "1.0";

	/**
	 * isv软件序列号
	 */
	private String appkey;

	/**
	 * 版本号
	 */
	private String v;

	/**
	 * 密钥
	 */
	private String secret;

	/**
	 * api服务地址
	 */
	private URL serviceUrl;

	/**
	 * http实现
	 */
	private UrlFetch fetch;

	public AbstractTaobaoRestClient(String serviceUrl, String version,
			String appkey, String secret) throws TaobaoApiException {
		try {
			this.serviceUrl = new URL(serviceUrl);
		} catch (MalformedURLException e) {
			throw new TaobaoApiException("Invalid url", e);
		}
		this.appkey = appkey;
		this.secret = secret;
		this.v = version;
		this.fetch = new HttpClient4UrlFetch();// default http implement
	}

	public AbstractTaobaoRestClient(String appkey, String secret)
			throws TaobaoApiException {
		this(appkey, secret, false);
	}

	public AbstractTaobaoRestClient(String appkey, String secret,
			boolean isSandbox) throws TaobaoApiException {
		this(isSandbox ? API_SANDBOX_SERVICE_URL : API_SERVICE_URL, appkey,
				secret);
	}

	public AbstractTaobaoRestClient(String serviceUrl, String appkey,
			String secret) throws TaobaoApiException {
		this(serviceUrl, DEFAULT_SERVICE_VERSION, appkey, secret);
	}

	protected String getApiKeyName() {
		return APIKEY;
	}

	protected String getMethodName() {
		return METHOD;
	}

	protected String getSignName() {
		return SIGN;
	}

	protected String getSessionIdName() {
		return SESSION;
	}

	protected String getTimestampName() {
		return TIMESTAMP;
	}

	protected URL getServiceUrl() {
		return serviceUrl;
	}

	public void setUrlFetch(UrlFetch fetch) {
		if (null == fetch) {
			return;
		}
		this.fetch = fetch;
	}

	protected UrlFetch getFetch() {
		return fetch;
	}

	/**
	 * 对调用API所需的参数进行包装 将请求request传入的参数包装成MAP对象
	 * 
	 * @param method
	 * @param session
	 * @param paramsMap
	 * @return
	 */
	protected Map<String, CharSequence> getTemplateRequest(String method,
			String session, Map<String, Object> paramsMap) {
		Map<String, CharSequence> request = new HashMap<String, CharSequence>();

		request.put(getApiKeyName(), appkey);
		request.put(getTimestampName(), getTimestamp());
		request.put(getMethodName(), method);
		if (session != null) {
			request.put(getSessionIdName(), session);
		}
		request.put(V, v);
		request.put(FORMAT, JSON_FORMAT);

		if (null != paramsMap) {
			Set<Entry<String, Object>> entries = paramsMap.entrySet();
			for (Entry<String, Object> entry : entries) {
				Object value = entry.getValue();
				if (null == value) {
					continue;
				}
				if (value instanceof Date) {
					request.put(entry.getKey(), DateUtil.dateToStr((Date) entry
							.getValue()));
				} else {
					request.put(entry.getKey(), entry.getValue().toString());
				}
			}
		}
		request.put(getSignName(), EncryptUtil.signature(request, secret,
				getSignName()));
		return request;
	}

	/**
	 * 对调用API所需的参数进行包装
	 * 
	 * @param method
	 * @param paramsMap
	 * @return
	 */
	protected Map<String, CharSequence> getTemplateRequest(String method,
			Map<String, Object> paramsMap) {
		return this.getTemplateRequest(method, null, paramsMap);
	}

	private String getTimestamp() {
		return DateUtil.dateToStr(new Date());
	}

}
